/*
 * Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
 *
 * Licensed under the Mulan PSL v2.
 * You can use this file according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of the License at
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
 * FOR MORE DETAILS.
 */

#pragma once

#include <unordered_map>

#include <highfive/H5File.hpp>

#include "DataStructure/Common/Id.h"
#include "DataStructure/Common/Out.h"

#include "DBManager/Common/DBManagerExport.h"
#include "DBManager/Common/DBManagerNamespace.h"

SG_DBMANAGER_HDF5_NAMESPACE_OPEN

// https://davis.lbl.gov/Manuals/HDF5-1.8.7/Advanced/Chunking/index.html
static const uint32_t DATASET_CHUNK_SIZE = 32 * 1024;         ///< 数据块大小 32KB
static const uint64_t DATASET_CACHE_SIZE = 32 * 1024 * 1024;  ///< 缓存大小 32MB

/**
 * @brief 用于存储HDF5文件中的索引缓存信息。
 */
struct IndexCache
{
    std::size_t minIndex = 0;  ///< 索引缓存的最小索引（左闭右闭区间）
    std::size_t maxIndex = 0;  ///< 索引缓存的最大索引（左闭右闭区间）
    std::string cacheKey{};    ///< 当前读取缓存在 CachePool 中的键
};

/**
 * @brief 用于存储表单信息，包括表单的属性和操作方法。
 */
struct DatasetInfo
{
  public:
    /**
     * @brief 创建表单。
     *
     * @param m_FileShdPtr HDF5文件的智能指针
     */
    void CreatTable (HighFive::File* m_FileShdPtr);

    /**
     * @brief 获取从指定索引开始的缓存区间及长度。
     *
     * @param loadIndex 要加载的索引
     * @param s_CacheSize 缓存大小
     * @param obegin 输出的开始索引
     * @param oLength 输出的长度
     */
    void CalcIndexBeginAndLength (std::size_t loadIndex, _OUT std::size_t& obegin, _OUT std::size_t& oLength, uint64_t cachesize) const;

    std::string GetPath () const
    {
        return m_path;
    }

    void SetPath (const std::string& path)
    {
        m_path = path;
    }

    std::size_t GetRowCount () const
    {
        return m_rowCount;
    }
    void SetRowCount (const std::size_t& rowCount)
    {
        m_rowCount = rowCount;
        m_isCreate = true;
    }

    bool IsSequential () const
    {
        return m_isSequential;
    }
    void SetIsSequential (bool isSequential)
    {
        m_isSequential = isSequential;
    }

    std::shared_ptr<HighFive::DataType> GetDataType () const
    {
        return m_dataType;
    }
    void SetDataType (const std::shared_ptr<HighFive::DataType>& dataType)
    {
        m_dataType = dataType;
    }

    std::size_t GetDataSize () const
    {
        return m_dataSize;
    }
    void SetDataSize (const std::size_t& dataSize)
    {
        m_dataSize = dataSize;
    }

    bool IsCreate ()
    {
        return m_isCreate;
    }

  private:
    bool        m_isCreate = false;      ///< 表单是否已经在文件中进行创建
    std::string m_path;                  ///< 数据集的路径，在InitialDatasetInfo中初始化
    bool        m_isSequential = false;  ///< 表单是否被排序过，每次调用dump()后变为false，排序后变为true
    std::size_t m_dataSize     = 0;      ///< 单个数据的大小，在InitialDatasetInfo中初始化
    std::size_t m_rowCount     = 0;      ///< 表单中的数据量，在初始化和WriteData时更新，(代表的是文件内的数据量，不包括写缓存中的)
    std::shared_ptr<HighFive::DataType> m_dataType = nullptr;  ///< 数据类型，在InitialDatasetInfo中初始化
};

SG_DBMANAGER_HDF5_NAMESPACE_CLOSE